package dictimpl

import (
	"context"
	"errors"
	"fmt"
	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/services/admin/dict"
	"go-caipu/pkg/services/admin/dict/models"
	"go-caipu/pkg/services/dto"
	"gorm.io/gorm"
	"time"
)

type store interface {
	GetSysDictTypePage(ctx context.Context, cmd dict.GetSysDictTypePageCommand) (data []dict.SysDictType, num int64, err error)
	Get(ctx context.Context, cmd dict.GetSysDictTypeCommand) (dict.SysDictType, error)
	Insert(ctx context.Context, post dict.SysDictType) error
	Update(ctx context.Context, post dict.SysDictType) error
	Remove(ctx context.Context, cmd dict.RemoveSysDictTypeCommand) error

	GetSysDictDataPage(ctx context.Context, cmd dict.GetSysDictDataPageCommand) (data []dict.SysDictData, num int64, err error)
	GetDictData(ctx context.Context, cmd dict.GetSysDictDataCommand) (dict.SysDictData, error)
	InsertDictData(ctx context.Context, cmd dict.SysDictData) error
	UpdateDictData(ctx context.Context, cmd dict.SysDictData) error
	RemoveDictData(ctx context.Context, cmd dict.RemoveSysDictDataCommand) error
	GetDictDataOptions(ctx context.Context, dictType string) (data []dict.Options, err error)
}
type sqlStore struct {
	db     *gorm.DB
	logger log.Logger
}

func ProvideStore(db *gorm.DB) sqlStore {
	return sqlStore{
		db:     db,
		logger: log.New("dept.store"),
	}
}

func (s sqlStore) GetSysDictTypePage(ctx context.Context, cmd dict.GetSysDictTypePageCommand) (result []dict.SysDictType, num int64, err error) {
	var items []models.SysDictType
	err = s.db.Model(&models.SysDictType{}).Scopes(
		dto.MakeCondition(cmd.GetNeedSearch()),
		dto.Paginate(cmd.GetPageSize(), cmd.GetPageIndex()),
	).Find(&items).Limit(-1).Offset(-1).Count(&num).Error
	if err != nil {
		return
	}
	for _, v := range items {
		result = append(result, ConvertToDTO(v))
	}
	return
}
func ConvertToDTO(model models.SysDictType) dict.SysDictType {
	result := dict.SysDictType{

		DictId:    model.DictId,
		DictName:  model.DictName,
		DictType:  model.DictType,
		Status:    model.Status,
		IsSystem:  model.IsSystem,
		Remark:    model.Remark,
		CreatedAt: model.CreatedAt.Format("2006-01-02 15:04:05"),
	}
	return result
}
func (s sqlStore) Get(ctx context.Context, cmd dict.GetSysDictTypeCommand) (result dict.SysDictType, err error) {
	var data models.SysDictType
	err = s.db.Model(&data).First(&data, cmd.DictId).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New(fmt.Sprintf("DictId=%d record Not found", cmd.DictId))
		return
	}
	if err != nil {
		s.logger.Log(fmt.Sprintf("get  dict=%d  error:%s", cmd.DictId, err.Error()))
		return
	}
	return ConvertToDTO(data), nil
}
func ConvertToDT(model dict.SysDictType, cmd *models.SysDictType) {
	cmd.DictId = model.DictId
	cmd.DictName = model.DictName
	cmd.DictType = model.DictType
	cmd.Status = model.Status
	cmd.Remark = model.Remark
}

func (s sqlStore) Insert(ctx context.Context, cmd dict.SysDictType) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysDictType
	ConvertToDT(cmd, &data)
	data.CreatedAt = time.Now()
	data.CreateBy = 0
	err = tx.Create(&data).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("insert  dict  error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Update(ctx context.Context, cmd dict.SysDictType) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	//查询当前名称是否存在
	var data models.SysDictType
	err = s.db.Model(&data).First(&data, cmd.DictId).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("check dict :%s is exists error:%s", cmd.DictName, err.Error()))
		return err
	}
	ConvertToDT(cmd, &data)
	data.UpdatedAt = time.Now()
	data.UpdateBy = 0

	err = tx.Save(&data).Error
	if err != nil {
		s.logger.Log(fmt.Sprintf("update  dict  error:%s", err.Error()))
		return err
	}
	return nil
}

func (s sqlStore) Remove(ctx context.Context, cmd dict.RemoveSysDictTypeCommand) (err error) {
	tx := s.db.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var data models.SysDictType
	//同时删除类型和值
	err = tx.Where("dict_id IN ? ", cmd.Ids).Delete(&models.SysDictData{}).Error
	err = tx.Model(&models.SysDictType{}).Delete(&data, "dict_id", cmd.Ids).Error
	if err != nil {
		return err
	}
	return
}
